/*
 * DesktopPaneDelegate.cpp  0.4.0 / Dec 04, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#include "DesktopPaneDelegate.h"

#include "InternalFrameDelegate.h"

// DesktopPaneDelegate :: Protected Constructor. -------------------------------

/*!
 * \brief Constructs new DesktopPaneDelegate object.
 *
 * \param env the JNIEnv pointer
 * \param obj the DesktopPane java object
 */
DesktopPaneDelegate::DesktopPaneDelegate(JNIEnv *env, jobject obj)
  : ContainerDelegate(env, obj, new QMdiArea())
{
  qMdiArea()->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  qMdiArea()->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
  qMdiArea()->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
  connectDirect(qMdiArea(), SIGNAL(subWindowActivated(QMdiSubWindow *)),
                SLOT(subWindowActivatedSlot(QMdiSubWindow *)));
}

// DesktopPaneDelegate :: Native Calls. ----------------------------------------

/*!
 * \brief Inserts child.
 *
 * \param env the JNIEnv pointer
 * \param childDelegate the child delegate
 * \param index the child index
 */
void DesktopPaneDelegate::insertChild(JNIEnv *env, jlong childDelegate,
                                      jint index)
{
  Q_UNUSED(index);
  Q_ASSERT(env);
  SWING_REENTRANT(insertChild, SWING_ENV_ARG, JLONG_ARG(childDelegate),
                  JINT_ARG(index))
  ComponentDelegate *childComponentDelegate = COMPONENT_CAST(childDelegate);
  QWidget *childWidget = childComponentDelegate->qWidget();
  QString tempTitle = childWidget->windowTitle();
  QPoint oldPosition = childWidget->pos();
  QSize oldSize = childWidget->size();
  setEventFilterEnabled(false);
  childComponentDelegate->setEventFilterEnabled(false);
  qMdiArea()->addSubWindow(childWidget);
  childComponentDelegate->setParentDelegate(this);
  if (oldPosition != childWidget->pos()) {
    childWidget->move(oldPosition);
  }
  if (oldSize != childWidget->size()) {
    childWidget->resize(oldSize);
  }
  childComponentDelegate->setEventFilterEnabled(true);
  setEventFilterEnabled(true);
  if (qMdiArea()->isVisible()) {
    childWidget->setVisible(true);
  }
}

/*!
 * \brief Removes the specified child.
 *
 * \param env the JNIEnv pointer
 * \param childDelegate the child delegate pointer
 */
void DesktopPaneDelegate::removeChild(JNIEnv *env, jlong childDelegate)
{
  Q_ASSERT(env);
  SWING_REENTRANT(removeChild, SWING_ENV_ARG, JLONG_ARG(childDelegate))
  qMdiArea()->removeSubWindow(COMPONENT_CAST(childDelegate)->qWidget());
  COMPONENT_CAST(childDelegate)->setParentDelegate(0);
}

/*!
 * \brief Sets current component.
 *
 * \param env the JNIEnv pointer
 * \param componentDelegate the component delegate pointer
 */
void DesktopPaneDelegate::setCurrentComponent(JNIEnv *env,
                                              jlong componentDelegate)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setCurrentComponent, SWING_ENV_ARG,
                  JLONG_ARG(componentDelegate))
  if (componentDelegate) {
    qMdiArea()->setActiveSubWindow(
                       INTERNAL_FRAME_CAST(componentDelegate)->qMdiSubWindow());
  } else {
    qMdiArea()->setActiveSubWindow(0);
  }
}

/*!
 * \brief Selects next comopnent.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::selectNextComponent(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(selectNextComponent, SWING_ENV_ARG)
  qMdiArea()->activateNextSubWindow();
}

/*!
 * \brief Selects previous component.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::selectPreviousComponent(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(selectPreviousComponent, SWING_ENV_ARG)
  qMdiArea()->activatePreviousSubWindow();
}

/*!
 * \brief Closes the current component.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::closeCurrentComponent(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(closeCurrentComponent, SWING_ENV_ARG)
  qMdiArea()->closeActiveSubWindow();
}

/*!
 * \brief Closes all components.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::closeAllComponents(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(closeAllComponents, SWING_ENV_ARG)
  qMdiArea()->closeAllSubWindows();
}

/*!
 * \brief Cascades the components.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::cascadeComponents(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(cascadeComponents, SWING_ENV_ARG)
  qMdiArea()->cascadeSubWindows();
}

/*!
 * \brief Tiles the components.
 *
 * \param env the JNIEnv pointer
 */
void DesktopPaneDelegate::tileComponents(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(tileComponents, SWING_ENV_ARG)
  qMdiArea()->tileSubWindows();
}

// DesktopPaneDelegate :: Static Native Calls. ---------------------------------

/*!
 * \brief Initializes DesktopPaneDelegate class.
 *
 * \param env the JNIEnv pointer
 * \param cls the DesktopPane java class
 *
 * \exception FatalError if failed
 */
void DesktopPaneDelegate::initialize(JNIEnv *env, jclass cls)
{
  Q_ASSERT(env);
  Q_ASSERT(cls);
  Q_ASSERT(!sm_activeComponentChangedMID);
  if (!INIT_UMID(activeComponentChanged, cls,
      "(Lcom/cute4j/swing/Component;)V")) {
    FATAL_LOGGED_ERROR("DesktopPaneDelegate initialization failed");
  }
}

/*!
 * \brief Returns new instance of the delegate object
 *
 * \param env the JNIEnv pointer
 * \param obj the Swing object
 * 
 * \return new instance of the delegate object
 */
jlong DesktopPaneDelegate::newInstance(JNIEnv *env, jobject obj)
{
  if (JNISwingWrapper::isSwingThread(env)) {
    return reinterpret_cast<jlong>(new DesktopPaneDelegate(env, obj));
  }
  return SwingUtilitiesDelegate::invokeLongAndWait(env, obj, createMID());
}

// DesktopPaneDelegate :: Native Callbacks. ------------------------------------

/*!
 * \brief Calls \c activeComponentChanged method of the desktop pane object.
 *
 * \param component the component
 */
void DesktopPaneDelegate::activeComponentChanged(jobject component)
{
  jniObject()->callVoidMethod(sm_activeComponentChangedMID, component);
}

// DesktopPaneDelegate :: Protected Member Function. ---------------------------

/*!
 * \brief Sub window activated slot.
 *
 * \param window the activated window
 */
void DesktopPaneDelegate::subWindowActivatedSlot(QMdiSubWindow *window)
{ 
  if (window) {
    InternalFrameDelegate *internalFrameDelegate  =
                       qObjectDelegatePointer<InternalFrameDelegate *>(window);
    activeComponentChanged(internalFrameDelegate->jniObject()->ref());
  } else {
    activeComponentChanged(0);
  }
}

// DesktopPaneDelegate :: Overridden Member Functions. -------------------------

/*!
 * \inheritDoc
 */
jobject DesktopPaneDelegate::getBackground(JNIEnv *env, jclass colorClass)
{
  return QColorAdapter::toJColor(env, colorClass,
                                 qMdiArea()->background().color());
}

/*!
 * \inheritDoc
 */
void DesktopPaneDelegate::setBackground(JNIEnv *env, jint argb)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setBackground, SWING_ENV_ARG, JINT_ARG(argb))
  qMdiArea()->setBackground(QColorAdapter(argb));
}

/*!
 * \inheritDoc
 */
void DesktopPaneDelegate::setNullBackground(JNIEnv *env)
{
  Q_ASSERT(env);
  SWING_REENTRANT(setNullBackground, SWING_ENV_ARG)
  qMdiArea()->setBackground(QApplication::palette().brush(QPalette::Dark));
}

// DesktopPaneDelegate :: Private Static Data Member. --------------------------

jmethodID DesktopPaneDelegate::sm_activeComponentChangedMID = 0;
